package com.jhf.youke.product.domain.service;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.jhf.youke.core.ddd.AbstractDomainService;
import com.jhf.youke.core.entity.PageQuery;
import com.jhf.youke.core.entity.Pagination;
import com.jhf.youke.core.utils.StringUtils;
import com.jhf.youke.product.domain.converter.ProductStyleConverter;
import com.jhf.youke.product.domain.gateway.ProductStyleRepository;
import com.jhf.youke.product.domain.model.Do.ProductStyleDo;
import com.jhf.youke.product.domain.model.po.ProductStylePo;
import com.jhf.youke.product.domain.model.vo.ProductStyleVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;



/**
 * @author RHJ
 */
@Service
public class ProductStyleService extends AbstractDomainService<ProductStyleRepository, ProductStyleDo, ProductStyleVo> {


    @Resource
    ProductStyleConverter productStyleConverter;

    @Override
    public boolean update(ProductStyleDo entity) {
        ProductStylePo productStylePo = productStyleConverter.do2Po(entity);
        productStylePo.preUpdate();
        updateParentIds(productStylePo, true);
        return repository.update(productStylePo);
    }

    @Override
    public boolean updateBatch(List<ProductStyleDo> doList) {
        List<ProductStylePo> poList = productStyleConverter.do2PoList(doList);
        return repository.updateBatch(poList);
    }

    @Override
    public boolean delete(ProductStyleDo entity) {
        ProductStylePo productStylePo = productStyleConverter.do2Po(entity);
        return repository.delete(productStylePo);
    }

    @Override
    public boolean deleteBatch(List<Long> idList) {
        return repository.deleteBatch(idList);
    }

    @Override
    public boolean insert(ProductStyleDo entity) {
        ProductStylePo productStylePo = productStyleConverter.do2Po(entity);
        productStylePo.preInsert();
        updateParentIds(productStylePo, false);
        return repository.insert(productStylePo);
    }

    /**
     * 更新上级ID集合
     * @param productStylePo
     * @return
     */
    private ProductStylePo updateParentIds(ProductStylePo productStylePo, Boolean isUpdate) {
        String parentTop = "0";
        if(productStylePo.getParentId() != null && !parentTop.equals(StringUtils.chgNull(productStylePo.getParentId()))){
            Optional<ProductStylePo> parentProductStyle = repository.findById(productStylePo.getParentId());
            productStylePo.setParentIds(parentProductStyle.get().getParentIds() + "," + productStylePo.getId());
        }else {
            productStylePo.setParentIds(productStylePo.getId().toString());
        }
        if(isUpdate) {
            Optional<ProductStylePo> oldProductStyle = repository.findById(productStylePo.getId());
            if(!oldProductStyle.get().getParentId().equals(productStylePo.getParentId())){
                //此次更新修改了父类ID，则需要更新此单位的下级单位父类集合
                updateSubParentIds(productStylePo);
            }
        }
        return productStylePo;
    }

    /**
     * 更新此下级的父类集合
     * @param productStylePo
     * @return
     */
    private void updateSubParentIds(ProductStylePo productStylePo) {
        ProductStylePo param = new ProductStylePo();
        param.setParentId(productStylePo.getId());
        List<ProductStylePo> subList = repository.findAllMatching(param);
        if(subList.size() == 0){
            return;
        }
        for(ProductStylePo item:subList){
            item.setParentIds(productStylePo.getParentIds() + "," + productStylePo.getId());
            repository.update(item);
            updateSubParentIds(item);
        }
    }

    @Override
    public boolean insertBatch(List<ProductStyleDo> doList) {
        List<ProductStylePo> poList = productStyleConverter.do2PoList(doList);
        poList = ProductStylePo.getInsertListId(poList);
        return repository.insertBatch(poList);
    }

    @Override
    public Optional<ProductStyleVo> findById(Long id) {
        Optional<ProductStylePo> productStylePo =  repository.findById(id);
        ProductStyleVo productStyleVo = productStyleConverter.po2Vo(productStylePo.orElse(new ProductStylePo()));
        return Optional.ofNullable(productStyleVo);

    }

    @Override
    public boolean remove(Long id) {
        return repository.remove(id);
    }

    @Override
    public boolean removeBatch(List<Long> idList) {
        return repository.removeBatch(idList);
    }

    @Override
    public List<ProductStyleVo> findAllMatching(ProductStyleDo entity) {
        ProductStylePo productStylePo = productStyleConverter.do2Po(entity);
        List<ProductStylePo>productStylePoList =  repository.findAllMatching(productStylePo);
        return productStyleConverter.po2VoList(productStylePoList);
    }


    @Override
    public Pagination<ProductStyleVo> selectPage(ProductStyleDo entity){
        ProductStylePo productStylePo = productStyleConverter.do2Po(entity);
        PageQuery<ProductStylePo> pageQuery = new PageQuery<>(productStylePo,entity.getCurrentPage(), entity.getPageSize(), entity.getQuerySort());
        Pagination<ProductStylePo> pagination = repository.selectPage(pageQuery);
        return new Pagination<ProductStyleVo>(pagination.getPageNum(),pagination.getPageSize(),pagination.getTotalSize(),
                productStyleConverter.po2VoList(pagination.getList()));
    }

    public List<ProductStyleVo> getListByRelease(Long companyId) {
        List<ProductStylePo> listPo = repository.getListByRelease(companyId);
        List<ProductStyleVo> list = productStyleConverter.po2VoList(listPo);
        return getTree(list);
    }

    public List<ProductStyleVo> getTreeByCompanyId(Long companyId) {
        ProductStyleDo param = new ProductStyleDo();
        param.setCompanyId(companyId);
        List<ProductStyleVo> list = findAllMatching(param);
        return getTree(list);
    }

    public List<ProductStyleVo> getTree(List<ProductStyleVo> list){
        Multimap<Long, ProductStyleVo> mulMap = ArrayListMultimap.create();
        List<ProductStyleVo> productStyleVoList = new ArrayList<>();
        for(ProductStyleVo productStyleVo : list){
            mulMap.put(productStyleVo.getParentId(), productStyleVo);
        }
        Collection<ProductStyleVo> productStyleVos = mulMap.get(0L);
        productStyleVos.forEach(productStyle -> {
            getSubTree(productStyle, mulMap);
            productStyleVoList.add(productStyle);
        });
        return productStyleVoList;
    }

    public ProductStyleVo getSubTree(ProductStyleVo menuVo, Multimap<Long, ProductStyleVo> mulMap){
        Collection<ProductStyleVo> productStyleVos = mulMap.get(menuVo.getId());
        menuVo.setSubList (new  ArrayList<>(productStyleVos));
        productStyleVos.forEach(productStyle -> {
            getSubTree(productStyle, mulMap);
        });
        return menuVo;
    }




}

